package player

import (
	"learn-opengl/camera"
	inputparam "learn-opengl/inputParam"
	"learn-opengl/scene"
	. "learn-opengl/util"
	"math"

	"github.com/go-gl/glfw/v3.2/glfw"
	"github.com/go-gl/mathgl/mgl32"
)

type Player struct {
	camera *camera.Camera
	scene *scene.Scene
}

func NewPlayer(camera *camera.Camera,scene *scene.Scene) *Player {
	return &Player{
		camera: camera,
		scene: scene,
	}
}

// 更新摄像机
// 增加碰撞检测
var preTime float64
var dd = 0.04
func (p *Player) Update(input *inputparam.Inputparam) {
	step := 5 * (glfw.GetTime() - preTime)
	preTime = glfw.GetTime()
	c := p.camera
	
	if input.Keys[glfw.KeyW] {
		c.CamePos = c.CamePos.Add(c.CameWFront.Mul(float32(step)))
	}
	if input.Keys[glfw.KeyS] {
		c.CamePos = c.CamePos.Sub(c.CameWFront.Mul(float32(step))) 
	}
	if input.Keys[glfw.KeyA] {
		c.CamePos = c.CamePos.Add(c.CameUp.Cross(c.CameWFront).Normalize().Mul(float32(step)))
	}
	if input.Keys[glfw.KeyD] {
		c.CamePos = c.CamePos.Sub(c.CameUp.Cross(c.CameWFront).Normalize().Mul(float32(step)))
	}
	if input.Keys[glfw.KeySpace] {
		c.CamePos = c.CamePos.Add(c.CameUp.Mul(3*float32(step)))
	}
	if input.Keys[glfw.KeyF] {
		c.CamePos = c.CamePos.Add(c.CameUp.Mul(5*float32(step)))
	}
	if input.Keys[glfw.KeyG] {
		c.CamePos = c.CamePos.Sub(c.CameUp.Mul(float32(step)))
	}
	if input.Button2 {
		p.Build()
	}
	

	dd += 0.04
	c.CamePos = mgl32.Vec3{c.CamePos[0],c.CamePos[1]-float32(step)*float32(dd),c.CamePos[2]}
	npos,stop := p.scene.CheckCollid(c.CamePos)
	if stop {
		dd = 0.04
	}
	c.CamePos = npos

	sensitity := 0.02
	c.Pitch += float32(sensitity) * input.Delte_mouse_Y
	c.Yaw += float32(sensitity) * input.Delte_mouse_X

	if c.Pitch > 89.0 {
		c.Pitch = 89.0
	} 
	if c.Pitch < -89.0 {
		c.Pitch = -89.0
	}

	c.CameFront[0] = Cos(Radians(c.Pitch)) * Cos(Radians(c.Yaw))
	c.CameFront[1] = Sin(Radians(c.Pitch))
	c.CameFront[2] = Cos(Radians(c.Pitch)) * Sin(Radians(c.Yaw))
	c.CameFront.Normalize()
	

	c.CameWFront = c.CameFront
	c.CameWFront[1] = 0
	c.CameWFront = c.CameWFront.Normalize()
	input.Clear()
}

// Build
func (p *Player) Build() {
	block := p.FindBlock(p.camera.CamePos, p.camera.CameFront)
	if block!=nil {
		p.scene.BuildBlock(*block,1)
	}
}

func NearBlock(Pos mgl32.Vec3) IV3 {
	return IV3{int(math.Round(float64(Pos[0]))),int(math.Round(float64(Pos[1]))),int(math.Round(float64(Pos[2])))}
}

// 找到一个方块
func (p *Player) FindBlock(pos mgl32.Vec3, vec mgl32.Vec3) *IV3 {
	var (
		maxLen = float32(8.0)
		step   = float32(0.125)
	)
	ori := NearBlock(pos)
	for len := float32(0); len < maxLen; len += step {
		cblock := NearBlock(pos.Add(vec.Mul(len)))
		if cblock!=ori && !p.scene.HasBlock(cblock)  {
			return &cblock
		}
	}
	return nil
}